using System;
using RockHopper.Common.Data;
using RockHopper.Common.Events;
using RockHopper.Common.Model;
using RockHopper.Common.Services;
using RockHopper.TrainingCalculator.WinRT.Utils;
using Windows.ApplicationModel;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace RockHopper.TrainingCalculator.WinRT.Controls
{
    public class RacePredictionControl : Control
    {
        public event EventHandler RemoveClick;

        private TextBlock labelTextBlock;
        private TextBlock raceTimeTextBlock;
        private TextBlock paceTextBlock;
        private Button removeButton;
        private static readonly ISettingsRepository settingsRepository;
        private static readonly ICalculationService calculationService;

        public RacePredictionControl()
        {
            DefaultStyleKey = typeof (RacePredictionControl);
            DomainEvents.PaceUnitsChanged += OnPaceUnitsChanged;
            DomainEvents.VdotChanged += OnVdotChanged;
        }

        static RacePredictionControl()
        {
            if (!DesignMode.DesignModeEnabled)
            {
                settingsRepository = Global.Container.Resolve<ISettingsRepository>();
                calculationService = Global.Container.Resolve<ICalculationService>();
            }   
        }

        public RaceDistance RaceDistance { get; private set; }
        
        private string RaceTime { get; set; }
        
        private string Pace { get; set; }
                        
        private double RaceTimeRaw { get; set; }

        public static RacePredictionControl Create(RaceDistance raceDistance)
        {
            var ctrl = new RacePredictionControl();
            ctrl.RaceDistance = raceDistance;
            var metres = ctrl.RaceDistance.Distance.ToMetres(ctrl.RaceDistance.Units);
            ctrl.RaceTimeRaw = calculationService.RaceTime(settingsRepository.Vdot, metres);
            ctrl.RaceTime = ctrl.RaceTimeRaw.FormatTime();
            ctrl.UpdateRacePace(settingsRepository.PaceUnits);
            return ctrl;
        }

        protected override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            labelTextBlock = (TextBlock) GetTemplateChild("LabelTextPart");
            labelTextBlock.Text = RaceDistance.ToString();
            raceTimeTextBlock = (TextBlock) GetTemplateChild("RaceTimeTextPart");
            raceTimeTextBlock.Text = RaceTime;
            paceTextBlock = (TextBlock) GetTemplateChild("PaceTextPart");
            paceTextBlock.Text = Pace;
            removeButton = (Button) GetTemplateChild("RemoveButtonPart");
            removeButton.Click += OnRemoveClick;
        }

        private void UpdateRacePace(PaceUnitType units)
        {
            var metres = RaceDistance.Distance.ToMetres(RaceDistance.Units);
            Pace = (1000 / (metres / RaceTimeRaw)).FormatPace(units).AppendPaceUnits(units);

            if (paceTextBlock != null)
                paceTextBlock.Text = Pace;
        }

        private void OnPaceUnitsChanged(object sender, PaceUnitsChangedEventArgs args)
        {
            UpdateRacePace(args.Units);
        }

        private void OnVdotChanged(object sender, VdotChangedEventArgs args)
        {
            var metres = RaceDistance.Distance.ToMetres(RaceDistance.Units);
            RaceTimeRaw = calculationService.RaceTime(args.Vdot, metres);
            RaceTime = RaceTimeRaw.FormatTime();
            UpdateRacePace(settingsRepository.PaceUnits);
            raceTimeTextBlock.Text = RaceTime;
            paceTextBlock.Text = Pace;
        }

        private void OnRemoveClick(object sender, RoutedEventArgs args)
        {
            DomainEvents.PaceUnitsChanged -= OnPaceUnitsChanged;
            DomainEvents.VdotChanged -= OnVdotChanged;
            RemoveClick(this, EventArgs.Empty);
        }
    }
}